#ifndef WIDGET_H
#define WIDGET_H

#include <string>
#include <Arduino.h>

#if defined(ESP8266)
    #include <WiFiClient.h>
    #include <ESP8266WiFi.h>
    #include <ESP8266WebServer.h>
    extern ESP8266WebServer* webGuiServer;
#elif defined(ESP32)
    #include <WiFi.h>
    #include <WiFiAP.h>
    #include <Arduino.h>
    #include <WebServer.h>
    #include <WiFiClient.h>
    extern WebServer* webGuiServer;
#endif
    
#define ON HIGH
#define OFF LOW
#define CLOSED HIGH
#define OPEN LOW
#define WEB_IO_LOGIC 0xFF
    
enum pointType {
    AI,
    AO,
    DI,
    DO
};
    
class IOPoint 
{
    public:
        int mode;
        int value;
        bool state;
        bool manual;
        uint8_t pin;
        std::string JS;
        std::string HTML;
        std::string loopFunc;
        std::string getValueUri;
        std::string setValueUri;
        std::string getOverrideUri;
        std::string setOverrideUri;
        pointType ioType;
        virtual void init();
        virtual void update();
        void setAnalog(int cmd);
        void setDigital(uint8_t cmd);
        int getAnalog();
        bool getDigital();
        void setUri(std::string name);
    private:
};

class DigitalInput : public IOPoint
{
    public:
        void init();
        void update();
        void toggle();
        void getState();
        void setOverride();
        void getOverride();
        DigitalInput(std::string name, int interval);
        DigitalInput(std::string name, uint8_t pin, uint8_t mode, int interval);
    private:
        void createWidget(std::string name, int interval);
};

class DigitalOutput : public IOPoint 
{
    public:
        void init();
        void update();
        void toggle();
        void getState();
        void setOverride();
        void getOverride();
        DigitalOutput(std::string name, int interval);
        DigitalOutput(std::string name, uint8_t pin, int interval);
    private:
        void createWidget(std::string name, int interval);
};

class AnalogInput : public IOPoint {
    public:
        float m = 1;
        float b = 0;
        void init();
        void update();
        void getValue();
        AnalogInput(std::string name, int interval);
        AnalogInput(std::string name, uint8_t pin, int interval);
    private:
        void createWidget(std::string name, int interval);
};

class AnalogOutput : public IOPoint {
    public:
        void init();
        void update();
        void setValue();
        void getValue();
        void setOverride();
        void getOverride();
        AnalogOutput(std::string name, int interval);
        AnalogOutput(std::string name, uint8_t pin, int interval);
    private:
        void createWidget(std::string name, int interval);
};

#endif

